// const arr = ['red', 'yellow', 'blue']
// arr[3] = 'black'

// console.log(arr.length)

// arr.length = 2

// console.log(arr, arr.length, arr[3])

// --------------------------------------

// const obj = {
//   a: 1,
//   b: 2
// }

// const proxy = new Proxy(obj, {
//   get(target, key) {
//     return Reflect.get(target, key)
//   }
// })

// console.log(proxy, proxy.a)

// -------------------------------------
// 简单的代理
// new Proxy() 需要两个参数 target 和 handler
// let target = {}
// let proxy = new Proxy(target, {})

// proxy.name = 'proxy'
// console.log(proxy.name)
// console.log(target.name)

// target.name = 'abc'
// console.log(proxy.name)
// console.log(target.name)

// ----------------------------------------
// set 陷阱函数
// target key value receiver（操作发生对象，一般指代理对象）
// let target = {
//   name: 'target'
// }

// // 构建值为数字的对象（不影响现有属性）
// let proxy = new Proxy(target, {
//   set(target, key, value, receiver) {
//     if (!target.hasOwnProperty(key)) {
//       if (isNaN(value)) {
//         throw new Error("First Of Property Value Must Number Type")
//       }
//     }

//     return Reflect.set(target, key, value, receiver)
//   }
// })

// proxy.count = 1
// console.log(proxy)
// proxy.count = 'asd'
// console.log(proxy)
// proxy.ansy = 'asd'
// console.log(proxy)

// --------------------------------------------------------
// get 陷阱
// target key receiver

// 未定义属性 js 中不报错
// let a = {}
// console.log(a.test)

// let proxy = new Proxy(a, {
//   get(target, key, receiver) {
//     console.log(target, key, receiver)
//     // if (!target.hasOwnProperty(key)) {
//     if (!(key in target)) {
//       throw new Error('This Object no this Property')
//     }
//     return Reflect.get(target, value, receiver)
//   }
// })

// console.log(proxy.test)

// ----------------------------------------------------
// has 陷阱
// target key

// let target = {
//   name: 'target',
//   value: 42
// }

// const proxy = new Proxy(target, {
//   has(target, key) {
//     if (key === 'value') {
//       return false
//     } else {
//       return Reflect.has(target, key)
//     }
//   }
// })

// console.log(('value' in proxy))
// console.log(('name' in proxy))

// ------------------------------------------
// deleteProperty 删除属性
// target key

// let target = {
//   name: 'wer',
//   age: 123
// }

// Object.defineProperty(target, 'name', {
//   configurable: false
// })
// console.log('name' in target)
// delete target.name // 严格模式下报错
// console.log('name' in target)

// const proxy = new Proxy(target, {
//   deleteProperty(target, key) {
//     console.log('Deleting')
//     if (key === 'name') {
//       return false
//     } else {
//       return Reflect.deleteProperty(target, key)
//     }
//   }
// })

// console.log('name' in proxy)
// delete proxy.name
// console.log('name' in proxy)

// ----------------------------------------------------------
// 原型代理陷阱
// setPrototypeOf & getPrototypeOf
// target proto
// getPrototype 陷阱返回值必须是 null || Object
// setPrototype 陷阱失败是必须返回false 否则视为成功

// let target = {}

// let proxy = new Proxy(target, {
//   getPrototypeOf(target) {
//     return null
//   },
//   setPrototypeOf(target, proto) {
//     return Reflect.setPrototypeOf(target, proto)
//   }
// })

// const targetProto = Object.getPrototypeOf(target)
// const proxyProto = Object.getPrototypeOf(proxy)

// console.log(targetProto === Object.prototype)
// console.log(proxyProto === Object.prototype)

// Reflect 底层操作，直对内部属性 [[GetPrototype]] 与 [[SetPrototype]]
// Object.getPrototypeOf 最开始就是面向开发者，参数会强制转为对象数据类型

// -----------------------------------------------------
// 对象可扩展性
// isExtensible & preventExtensions
// target
// let target = {}
// let proxy = new Proxy(target, {
//   isExtensible(target) {
//     return Reflect.isExtensible(target)
//   },
//   preventExtensions(target) {
//     return Reflect.preventExtensions(target)
//   }
// })

// proxy.a = 1
// console.log(Object.isExtensible(target), target)
// console.log(Object.isExtensible(proxy), proxy)

// Object.preventExtensions(proxy)

// proxy.b = 1
// console.log(Object.isExtensible(target), target)
// console.log(Object.isExtensible(proxy), proxy)


// ------------------------------------------------
// 属性描述符 陷阱
// defineProperty & getOwnPropertyDescriptor
// target key descriptor
// defineProperty 返回值必须是：null、undefined、Object（get/set/writable/value/configurable/enumerable）

// let proxy = new Proxy({}, {
//   getOwnPropertyDescriptor(target, key) {
//     return Reflect.getOwnPropertyDescriptor(target, key)
//   },
//   defineProperty(target, key, descriptor) {
//     return Reflect.defineProperty(target, key, descriptor)
//   }
// })

// -------------------------------------------------
// ownKeys 陷阱
// 拦截内部方法 [[OwnPropertyKeys]]

// let proxy = new Proxy({}, {
//   ownKeys(target) {
//     return Reflect.ownKeys(target).filter(key => {
//       return typeof key !== 'string' || key[0] === '_'
//     })
//   }
// })

// ------------------------------------------------
// 函数对象 apply 和 construct

/**
 * apply
 * target thisArg argList
 */

/**
 * construct
 * target argList
 */

// let target = function () { return 42 }
// let proxy = new Proxy(target, {
//   apply(target, thisArg, argumentList) {
//     console.log('执行')
//     return Reflect.apply(target, thisArg, argumentList)
//   },
//   construct(target, argList) {
//     return Reflect.construct(target, argList)
//   }
// })

// console.log(typeof proxy)
// console.log(proxy())

// --------------------------------------------
// 覆写抽象基类

// class Car {
//   constructor(...values) {
//     if (new.target === Car) {
//       console.log('该类只能被继承，无法创建')
//     }

//     this.values = values
//   }

//   go() {
//     console.log('abc', ...this.values)
//   }
// }

// class SmallCar extends Car {
//   constructor(...values) {
//     super(...values)
//   }

//   leaf() {
//     console.log('keaf')
//   }
// }

// const proxy = new Proxy(Car, { // 绕开构造限制，设置新的 new.target 指向
//   construct(target, argumentList) {
//     return Reflect.construct(target, argumentList, function () { })
//   }
// })

// const car = new Car(1, 2, 3)
// const smallCar = new SmallCar(1, 2, 3)
// const car_proxy = new proxy(123)
// smallCar.go()
// console.log(car_proxy, car_proxy.values)
// // car_proxy.go()

// ----------------------------------------------------
// 创建可撤销的代理
// Proxy.revocable()
// 返回值：
//  proxy(代理对象) revoke(撤销代理的调用函数)

let target = {
  name: 'wer'
}

let { proxy, revoke } = Proxy.revocable(target, {})
console.log(proxy.name)

revoke()

console.log(proxy.name)









